package com.wimcorp.magic.abilities;

import java.rmi.RemoteException;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.wimcorp.magic.abilities.trigger.AbilityTrigger;
import com.wimcorp.magic.exception.CastException;
import com.wimcorp.magic.exception.CostException;
import com.wimcorp.magic.input.Condition;
import com.wimcorp.magic.input.Target;
import com.wimcorp.magic.phase.Turn;

/**
 * 
 * condition : MORBID
 * 
 * 
 */
@Entity
@Table(name = "conditionability", schema = "abilities")
public class ConditionAbility extends Ability {

	@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	private Ability nonConditionAbility;
	@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	private Ability conditionAbility;

	@Enumerated(EnumType.STRING)
	private Condition condition;

	@Transient
	private Boolean conditionFullFilled = null;

	protected ConditionAbility() {
	}

	public ConditionAbility(AbilityTrigger trigger, Ability nonConditionAbility, Ability conditionAbility,
			Condition condition) {
		super(trigger);
		this.nonConditionAbility = nonConditionAbility;
		this.conditionAbility = conditionAbility;
		this.condition = condition;
	}

	public ConditionAbility(ConditionAbility ability) {
		super(ability);
		if (ability.getNonConditionAbility() != null) {
			ability.getNonConditionAbility().setCard(ability.getCard());
			this.nonConditionAbility = ability.getNonConditionAbility().clone();
		}
		if (ability.getConditionAbility() != null) {
			ability.getConditionAbility().setCard(ability.getCard());
			this.conditionAbility = ability.getConditionAbility().clone();
		}
		this.condition = ability.getCondition();
	}

	@Override
	public void configure() throws RemoteException {
		// if (isInputRequired()) {
		if (isConditionFullFilled()) {
			if (conditionAbility != null) {
				conditionAbility.configure();
			}
		} else {
			if (nonConditionAbility != null) {
				nonConditionAbility.configure();
			}
		}
		// getPlayer().messageOpponent(
		// String.format("Opponent %s played %s with target %s",
		// getPlayer().getName(), getCard().getName(),
		// getAbilityTarget().getName()));
		// } else {
		// getPlayer().messageOpponent(String.format("Opponent %s played %s ",
		// getPlayer().getName(), getCard().getName()));
		// }
	}

	@Override
	protected void executeAbility() throws CastException {

		if (nonConditionAbility != null && !isConditionFullFilled()) {
			nonConditionAbility.executeAbility();
		}
		if (conditionAbility != null && isConditionFullFilled()) {
			conditionAbility.executeAbility();
		}
	}

	public void uncast() {
		if (nonConditionAbility != null) {
			nonConditionAbility.uncast();
		}
		if (conditionAbility != null) {
			conditionAbility.uncast();
		}
	}

	private boolean isConditionFullFilled() {
		if (conditionFullFilled == null) {
			conditionFullFilled = false;
			switch (condition) {
			case MORBID:
				conditionFullFilled = Turn.isMorbid();
			case KICKER:
				try {
					boolean kicked = getPlayer().getUserInterface().selectBoolean(
							String.format("Would you like to kick %s. ", getCard().getName()));
					if (kicked) {
						boolean retry = false;
						do {
							try {
								conditionAbility.payCost();
								conditionFullFilled = true;
							} catch (CostException e) {
								getPlayer().message(e.getMessage());
								retry = getPlayer().getUserInterface().selectBoolean("Would you like to try again?");
							}
						} while (retry);
					}
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
		}
		return conditionFullFilled;
	}

	public Ability getNonConditionAbility() {
		return nonConditionAbility;
	}

	public Ability getConditionAbility() {
		return conditionAbility;
	}

	public Condition getCondition() {
		return condition;
	}

	@Override
	public Ability clone() {
		return new ConditionAbility(this);
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder("		id : " + getIdentifier());
		sb.append("\n");
		if (nonConditionAbility != null) {
			sb.append("		" + nonConditionAbility.getDescription());
			sb.append("\n");
		}
		if (conditionAbility != null) {
			sb.append("		" + conditionAbility.getDescription());
			sb.append("\n");
		}
		return sb.toString();
	}

	@Override
	public boolean isInputRequired() {
		if (nonConditionAbility != null && nonConditionAbility.isInputRequired()) {
			return true;
		} else if (conditionAbility != null && conditionAbility.isInputRequired()) {
			return true;
		}
		return false;
	}

	public void register() {
		if (conditionFullFilled == null) {
			conditionFullFilled = isConditionFullFilled();
		}
		if (nonConditionAbility != null && !isConditionFullFilled()) {
			AbilityTrigger trigger = nonConditionAbility.getTrigger();
			trigger.getAbility().setCard(getCard());
			trigger.register();
		}
		if (conditionAbility != null && isConditionFullFilled()) {
			AbilityTrigger trigger = conditionAbility.getTrigger();
			trigger.getAbility().setCard(getCard());
			trigger.register();
		}
	}

	public void unRegister() {
		if (nonConditionAbility != null) {
			nonConditionAbility.getTrigger().unRegister();
		}
		if (conditionAbility != null) {
			conditionAbility.getTrigger().unRegister();
		}
	}

}
